package com.jxpanda.infrastructure.crypto.constant;

import com.jxpanda.infrastructure.crypto.algorithm.encrypt.AesEncrypt;
import com.jxpanda.infrastructure.crypto.algorithm.encrypt.DesEncrypt;
import com.jxpanda.infrastructure.crypto.algorithm.encrypt.EcEncrypt;
import com.jxpanda.infrastructure.crypto.algorithm.encrypt.RsaEncrypt;
import com.jxpanda.infrastructure.crypto.key.AesKeyProvider;
import com.jxpanda.infrastructure.crypto.key.DesKeyProvider;
import com.jxpanda.infrastructure.crypto.key.EcKeyPairProvider;
import com.jxpanda.infrastructure.crypto.key.RsaKeyPairProvider;
import com.jxpanda.infrastructure.crypto.key.contract.KeyPairProvider;
import com.jxpanda.infrastructure.crypto.key.contract.SecretKeyProvider;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.security.spec.AlgorithmParameterSpec;

public final class AlgorithmEncrypt {


    public interface Symmetric {
        String getAlgorithm();

        SecretKeyProvider keyProvider();
    }


    @Getter
    @RequiredArgsConstructor
    public enum AES implements Symmetric {
        /**
         * AES算法，只枚举常用的，不常用的以后遇到了再补充
         * 注：AES是简写，等价于：AES/ECB/PKCS5Padding
         */
        AES("AES"),
        AES_CBC("AES/CBC/NoPadding"),
        AES_CBC_PKCS5("AES/CBC/PKCS5Padding"),
        AES_CBC_PKCS7("AES/CBC/PKCS7Padding"),
        AES_ECB("AES/ECB/NoPadding"),
        AES_ECB_PKCS5("AES/ECB/PKCS5Padding"),
        AES_ECB_PKCS7("AES/ECB/PKCS7Padding");

        public static final String KEY_ALGORITHM = "AES";
        public static final int KEY_LENGTH = 128;
        public static final int IV_LENGTH = 16;

        private final String algorithm;

        @Override
        public AesKeyProvider keyProvider() {
            return new AesKeyProvider();
        }

        public AesEncrypt.Builder builder() {
            return AesEncrypt.builder(this);
        }

    }

    @Getter
    @RequiredArgsConstructor
    public enum DES implements Symmetric {
        /**
         * DES算法，只枚举常用的，不常用的以后遇到了再补充
         * 注：DES是简写，等价于：DES/CBC/PKCS5Padding
         */
        DES("DES"),
        DES_CBC("DES/CBC/NoPadding"),
        DES_CBC_PKCS5("DES/CBC/PKCS5Padding"),
        DES_CBC_PKCS7("DES/CBC/PKCS7Padding"),
        DES_ECB("DES/ECB/NoPadding"),
        DES_ECB_PKCS5("DES/ECB/PKCS5Padding"),
        DES_ECB_PKCS7("DES/ECB/PKCS7Padding");

        public static final String KEY_ALGORITHM = "DES";
        public static final int KEY_LENGTH = 56;
        public static final int IV_LENGTH = 8;

        private final String algorithm;

        public DesKeyProvider keyProvider() {
            return new DesKeyProvider();
        }

        public DesEncrypt.Builder builder() {
            return DesEncrypt.builder(this);
        }

    }


    public interface Asymmetric {

        String getAlgorithm();

        KeyPairProvider<? extends AlgorithmParameterSpec> keyPairProvider();

    }

    @Getter
    @RequiredArgsConstructor
    public enum RSA implements Asymmetric {
        /**
         * RSA加密算法，需要引入BouncyCastle包提供支持
         */
        RSA("RSA"),
        RSA_ECB_PKCS1("RSA/ECB/PKCS1Padding"),
        RSA_ECB_OAEP("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"),
        RSA_ECB_OAEP_SHA256("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        private final String algorithm;

        public static final String KEY_ALGORITHM = "RSA";
        public static final int KEY_BITS_1024 = 1024;
        public static final int KEY_BITS_2048 = 2048;
        public static final int KEY_BITS_3072 = 3072;
        public static final int KEY_BITS_4096 = 4096;


        @Override
        public RsaKeyPairProvider keyPairProvider() {
            return new RsaKeyPairProvider();
        }

        public RsaEncrypt.Builder builder() {
            return RsaEncrypt.builder(this);
        }

    }

    @Getter
    @RequiredArgsConstructor
    public enum EC implements Asymmetric {

        /**
         * EC椭圆曲线加密算法，需要引入BouncyCastle包提供支持
         */
        ECIES("ECIES", null, null),
        ECIES_WITH_SHA1("ECIESwithSHA1andAES-CBC", -1, 256),
        ECIES_WITH_SHA256("ECIESwithSHA256andAES-CBC", 256, 256),
        ECIES_WITH_SHA384("ECIESwithSHA384andAES-CBC", 384, 256),
        ECIES_WITH_SHA512("ECIESwithSHA512andAES-CBC", 512, 256);

        private final String algorithm;

        private final Integer macKeySize;

        private final Integer cipherKeySize;


        public static final String KEY_ALGORITHM = "EC";
        public static final String CURVE_SECP_192_R1 = "secp192r1";
        public static final String CURVE_SECP_256_R1 = "secp256r1";
        public static final String CURVE_SECP_384_R1 = "secp384r1";
        public static final String CURVE_SECP_521_R1 = "secp521r1";
        public static final String CURVE_SECP_256_K1 = "secp256k1";
        public static final String CURVE_BRAINPOOL_P256_R1 = "brainpoolP256r1";
        public static final String CURVE_BRAINPOOL_P384_R1 = "brainpoolP384r1";
        public static final String CURVE_BRAINPOOL_P512_R1 = "brainpoolP512r1";
        public static final int DEFAULT_SECURE_LENGTH = 16;

        @Override
        public EcKeyPairProvider keyPairProvider() {
            return new EcKeyPairProvider();
        }

        public EcEncrypt.Builder builder() {
            return EcEncrypt.builder(this);
        }

    }

}
